package com.fs.console.yuezi.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.baseMapper.UserMapper;
import com.fs.common.pojo.Order;
import com.fs.common.pojo.Product;
import com.fs.common.pojo.User;
import com.fs.common.pojo.WechatPayConfig;
import com.fs.common.service.UserService;
import com.fs.common.utils.ConcurrentHashMapCacheUtils;
import com.fs.common.yzMapper.OrderMapper;
import com.fs.common.yzMapper.ProductMapper;
import com.fs.common.yzMapper.WechatPayConfigMapper;
import com.fs.console.base.annotation.PassToken;
import com.fs.console.base.enums.CodeEnum;
import com.fs.console.base.utils.ApplicationUtils;
import com.fs.console.base.utils.DateUtils;
import com.fs.console.base.vo.JsonResponse;
import com.fs.wechat.constants.WXConstants;
import com.fs.wechat.service.WechatPayService;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**
 * @author DeveloperKK
 * @desc 微信支付接口
 * @creationTime 2019-08-20 17:40
 * @projectName yuezi-menu
 * @packageName com.fs.console.wechat
 */
@Slf4j
@Controller
@RequestMapping("/wechat/pay")
public class WeChatPayController {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private WechatPayConfigMapper wechatPayConfigMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private WechatPayService wxPayService;
    @Autowired
    private UserMapper userMapper;
    /**
     * 创建订单接口
     * @param request
     * @return
     *
     */
    @ResponseBody
    @PostMapping("/createOrder")
    @ApiOperation(value = "创建订单")
    //@PassToken
    public JsonResponse createOrder(HttpServletRequest request,String code,String openId){
        try {
            if (StringUtils.isBlank(openId)) {
                JSONObject jsonObj = wxPayService.code2Session(code);
                openId = (String)jsonObj.get("openid");
            }
            if (StringUtils.isNotBlank(openId)) {
                Order order = getOrder( request.getRemoteAddr(), openId);
                WxPayMpOrderResult wxPayMpOrderResult = wxPayService.createOrder(order);
                if (wxPayMpOrderResult == null) {
                    throw new RuntimeException("下单失败！");
                }
                orderMapper.insert(order);
                JSONObject jsonObj = JSON.parseObject(JSON.toJSONString(wxPayMpOrderResult));
                jsonObj.put("openId",openId);
                jsonObj.put("outTradeNo",order.getOutTradeNo());
                return JsonResponse.success(jsonObj);
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            if (e instanceof WxPayException) {
                return JsonResponse.error(e.getMessage());
            }
        }
        return JsonResponse.error(CodeEnum.EX999);
    }

    /**
     * 查询订单接口
     * @param outTradeNo
     * @return
     */
    @ResponseBody
    @PostMapping("/queryOrder")
    @ApiOperation(value = "查询订单结果接口")
    //@PassToken
    public JsonResponse queryOrder(String outTradeNo){
        try {
            if (StringUtils.isNotBlank(outTradeNo)) {
                Order order =  orderMapper.findByOutTradeNo(outTradeNo);
                String orderStatus = order.getOrderStatus();
                if (order != null && order.getVersion() == 0) {
                    WxPayOrderQueryResult result = wxPayService.queryOrder(null, outTradeNo);
                    if (result == null || "FAIL".equalsIgnoreCase(result.getReturnCode())) {
                        throw  new WxPayException("查询订单失败！");
                    }
                    order.setOrderStatus(result.getTradeState());
                    if ("SUCCESS".equalsIgnoreCase(result.getTradeState())) {
                        order.setTransactionId(result.getTransactionId());
                        order.setTradeType(result.getTradeType());
                        order.setTotalFee(result.getTotalFee());
                        order.setResultCode(result.getResultCode());
                        order.setSettlementTotalFee(result.getSettlementTotalFee());
                        if (result.getTimeEnd()!= null) {
                            order.setTimeEnd(DateUtils.parseDate(result.getTimeEnd(),"yyyyMMddHHmmss"));
                        }
                        userService.rechargeCount(ApplicationUtils.getUser().getUser().getId(),order);
                        userService.rechargeIntegral(ApplicationUtils.getUser().getUser(),order);
                        log.info("订单号："+order.getOutTradeNo()+" 充值成功，" +
                                "金额："+ order.getTotalFee()+"，次数："+order.getCheckNumber()+
                                "支付订单号："+order.getTransactionId());
                    }
                    if (!orderStatus.equals(order.getOrderStatus())) {//状态变化时更新
                        if ("REVOKED".equals(order.getOrderStatus())
                                || "CLOSED".equals(order.getOrderStatus())
                                || "REVOKED".equals(order.getOrderStatus())
                                || "SUCCESS".equals(order.getOrderStatus())) {
                            order.setVersion(1);//版本控制
                        }
                        orderMapper.updateById(order);
                    }
                    return JsonResponse.success(order);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            if (e instanceof WxPayException) {
                return JsonResponse.error(e.getMessage());
            }
        }
        return JsonResponse.error(CodeEnum.EX999);
    }

    @ResponseBody
    @PostMapping("/getLoginUser")
    @ApiOperation(value = "获取当前登录信息")
    public JsonResponse getLoginUser(){
        User user = userMapper.selectById(ApplicationUtils.getUserId());
        return JsonResponse.success(user);
    }

    /**
     * 对外暴露的支付结果通知接口
     * @param xmlData
     * @return
     */
    @ResponseBody
    @PostMapping("/notifyPayResult")
    @ApiOperation(value = "对外暴露的支付结果通知接口")
    @PassToken
    public String notifyPayResult(@RequestBody String xmlData){
        try {
            WxPayOrderNotifyResult result = wxPayService.wxPayOrderNotifyResult(xmlData);
            if (result != null) {
                Order order = fromResult(result);
                if (StringUtils.isNotBlank(order.getId()) && order.getVersion() == 0) {
                    if ("SUCCESS".equals(order.getResultCode())) {
                        order.setOrderStatus("SUCCESS");
                        userService.rechargeCount(ApplicationUtils.getUser().getUser().getId(),order);
                        userService.rechargeIntegral(ApplicationUtils.getUser().getUser(),order);
                    } else {
                        order.setOrderStatus("PAYERROR");
                    }
                    orderMapper.updateById(order);
                }
                return WxPayNotifyResponse.success("成功！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return WxPayNotifyResponse.fail("失败！");
    }



    private Order fromResult(WxPayOrderNotifyResult result){
        Order order = new Order();
        if (result != null) {
            String tradeNo = result.getOutTradeNo();
            order= orderMapper.findByOutTradeNo(tradeNo);
            if (order != null) {
                order.setTotalFee(result.getTotalFee());
                order.setResultCode(result.getResultCode());
                order.setSettlementTotalFee(result.getSettlementTotalFee());
                if (result.getTimeEnd()!= null) {
                    order.setTimeEnd(DateUtils.parseDate(result.getTimeEnd(),"yyyyMMddHHmmss"));
                }
                order.setTradeType(result.getTradeType());
                order.setTransactionId(result.getTransactionId());
            }
        }
        return order;
    }


    private Order getOrder( String ipAddress, String openid){
        Product p = getProduct();
        Order order = new Order();
        order.setOpenid(openid);
        order.setIpAddress(ipAddress);
        order.setCheckNumber(p.getCount());
        order.setOrderName(p.getName());
        order.setTotalFee(p.getPrice());
        order.setProductId(p.getId());
        order.setTradeType(WXConstants.JSAPI);
        order.setOrderStatus("NOTPAY");
        order.setOrderType(0);//订单类型 0支付 1充值
        order.setPayType(0);//支付类型 0微信小程序支付 1微信扫码支付
        order.setOutTradeNo(DateUtils.curDate("yyyyMMddHHmmssSSS"));
        order.setCreaterId(ApplicationUtils.getUser().getUser().getId());
        return order;
    }

    /**
     * 计算单次购买金额(依次递减5%，最多三次)
     * @return
     */
    private Integer getPrice(Integer price,Integer count){
        Double aDouble = price.doubleValue();
        int i = 0;
        if(count < 1){
            return price;
        }else if(count < 2){
            i = new Double(aDouble * 0.95).intValue();
        }else if(count < 3){
            i = new Double(aDouble * 0.90).intValue();
        }else{
            i = new Double(aDouble * 0.85).intValue();
        }
        if(i <= 0){
            i = 1;
        }
        return i;
    }

    private Product getProduct(){
        User user = ApplicationUtils.getUser().getUser();
        Product product = productMapper.selectById(user.getProductId());
        if(product.getType().equals("basic")){
            product.setPrice(getPrice(product.getExceedPrice(),user.getBuyCount()));
        }
        return product;
    }

    private WechatPayConfig getWPC(){
        WechatPayConfig wpc = (WechatPayConfig) ConcurrentHashMapCacheUtils.getCache(WechatPayConfig.CACHE_KEY);
        if (wpc == null) {
            wpc = wechatPayConfigMapper.selectById(1);
            ConcurrentHashMapCacheUtils.setCache(WechatPayConfig.CACHE_KEY,wpc);
        }
        return wpc;
    }
}
